package com.jeesuite.admin.controller.admin;

import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.jeesuite.admin.dao.entity.AppEntity;
import com.jeesuite.admin.dao.entity.AppconfigEntity;
import com.jeesuite.admin.dao.mapper.AppEntityMapper;
import com.jeesuite.admin.dao.mapper.AppconfigEntityMapper;
import com.jeesuite.admin.exception.JeesuiteBaseException;
import com.jeesuite.admin.model.KeyValuePair;
import com.jeesuite.admin.model.WrapperResponseEntity;
import com.jeesuite.admin.model.request.AddOrEditAppRequest;
import com.jeesuite.admin.model.request.AddOrEditConfigRequest;
import com.jeesuite.admin.model.request.EncryptRequest;
import com.jeesuite.admin.model.request.QueryConfigRequest;
import com.jeesuite.admin.util.CryptUtils;
import com.jeesuite.admin.util.SecurityUtil;
import com.jeesuite.common.util.BeanCopyUtils;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

@Controller
@RequestMapping("/admin/cc")
public class ConfigCenterAdminController {

	private @Autowired AppEntityMapper appMapper;
	private @Autowired AppconfigEntityMapper appconfigMapper;
	
	@RequestMapping(value = "apps", method = RequestMethod.GET)
	public ResponseEntity<WrapperResponseEntity> findAllApps(){
		List<AppEntity> list = appMapper.selectAll();
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(list),HttpStatus.OK);
	}
	
	@RequestMapping(value = "app/{id}", method = RequestMethod.GET)
	public ResponseEntity<WrapperResponseEntity> getApp(@PathVariable("id") int id){
		AppEntity entity = appMapper.selectByPrimaryKey(id);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(entity),HttpStatus.OK);
	}
	
	@RequestMapping(value = "app/add", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> addApp(@RequestBody AddOrEditAppRequest addAppRequest){
		SecurityUtil.requireSuperAdmin();
		Example example = new Example(AppEntity.class);
		example.createCriteria().andEqualTo("name", addAppRequest.getName());
		int count = appMapper.selectCountByExample(example);
		if(count > 0){
			throw new JeesuiteBaseException(1002, "应用["+addAppRequest.getName()+"]已存在");
		}
		AppEntity appEntity = BeanCopyUtils.copy(addAppRequest, AppEntity.class);
		appEntity.setSecret(UUID.randomUUID().toString().replaceAll("-", ""));
		appMapper.insertSelective(appEntity);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(true),HttpStatus.OK);
	}
	
	@RequestMapping(value = "app/update", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> updateApp(@RequestBody AddOrEditAppRequest addAppRequest){
		SecurityUtil.requireSuperAdmin();
		AppEntity app = appMapper.selectByPrimaryKey(addAppRequest.getId());
		if(app == null){
			throw new JeesuiteBaseException(1002, "应用不存在");
		}
		AppEntity appEntity = BeanCopyUtils.copy(addAppRequest, AppEntity.class);
		appMapper.updateByPrimaryKeySelective(appEntity);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(true),HttpStatus.OK);
	}
	
	@RequestMapping(value = "app/delete/{id}", method = RequestMethod.GET)
	public ResponseEntity<WrapperResponseEntity> deleteApp(@PathVariable("id") int id){
		SecurityUtil.requireSuperAdmin();
		int delete = appMapper.deleteByPrimaryKey(id);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(delete > 0),HttpStatus.OK);
	}
	
	@RequestMapping(value = "config/upload", method = RequestMethod.POST)
	public ResponseEntity<Object> uploadConfigFile(@RequestParam("file") CommonsMultipartFile file){
		try {
			String fileName = null;
			StringBuilder content = new StringBuilder();
			List<String> lines = IOUtils.readLines(file.getInputStream(), StandardCharsets.UTF_8);
			for (String line : lines) {
				if (StringUtils.isBlank(line))
					continue;
				if (line.contains("--"))
					continue;
				if (line.contains("filename=")) {
					fileName = line.split("filename=")[1].replace("\"", "");
					continue;
				}
				if (line.startsWith("Content-"))
					continue;
				if (fileName == null)
					continue;
				content.append(line).append("\n");
			}
			
			return new ResponseEntity<Object>(new WrapperResponseEntity(content.toString()),HttpStatus.OK);
		} catch (Exception e) {
			throw new JeesuiteBaseException(9999, "上传失败");
		}
	}
	
	@RequestMapping(value = "config/{id}", method = RequestMethod.GET)
	public ResponseEntity<WrapperResponseEntity> getConfig(@PathVariable("id") int id){
		AppconfigEntity entity = appconfigMapper.selectByPrimaryKey(id);
		SecurityUtil.requireProfileGanted(entity.getEnv());
		
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(entity),HttpStatus.OK);
	}
	
	@RequestMapping(value = "config/add", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> addConfig(@RequestBody AddOrEditConfigRequest addRequest){
		
		SecurityUtil.requireProfileGanted(addRequest.getEnv());
		
		Example example = new Example(AppconfigEntity.class);
		if(addRequest.getGlobal() == 1){
			addRequest.setAppName("global");
		}
		example.createCriteria().andEqualTo("name", addRequest.getName())
		                        .andEqualTo("env", addRequest.getEnv())
		                        .andEqualTo("appName", addRequest.getAppName())
		                        .andEqualTo("version", addRequest.getVersion());
		int count = appconfigMapper.selectCountByExample(example);
		if(count > 0){
			throw new JeesuiteBaseException(1002, "配置["+addRequest.getName()+"]["+addRequest.getEnv()+"]["+addRequest.getVersion()+"]已存在");
		}
		AppconfigEntity entity = BeanCopyUtils.copy(addRequest, AppconfigEntity.class);
		appconfigMapper.insertSelective(entity);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(true),HttpStatus.OK);
	}
	
	@RequestMapping(value = "config/update", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> updateConfig(@RequestBody AddOrEditConfigRequest addRequest){
		if(addRequest.getId() == null || addRequest.getId() == 0){
			throw new JeesuiteBaseException(1003, "id参数缺失");
		}
		AppconfigEntity entity = appconfigMapper.selectByPrimaryKey(addRequest.getId());
		SecurityUtil.requireProfileGanted(entity.getEnv());
		
		entity.setName(addRequest.getName());
		entity.setContents(addRequest.getContents());
		appconfigMapper.updateByPrimaryKeySelective(entity);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(true),HttpStatus.OK);
	}
	
	@RequestMapping(value = "config/download/{id}", method = RequestMethod.GET)
	public void downConfigFile(@PathVariable("id") int id,HttpServletResponse response){
		AppconfigEntity config = appconfigMapper.selectByPrimaryKey(id);
		
		SecurityUtil.requireProfileGanted(config.getEnv());
		OutputStream output = null;
		try {
			String content = config.getContents();
			response.addHeader("Content-Disposition", "attachment;filename=" + new String(config.getName().getBytes()));
			response.addHeader("Content-Length", "" + content.length());
			output = new BufferedOutputStream(response.getOutputStream());
			response.setContentType("application/octet-stream");
			byte[] bytes = content.getBytes();
			output.write(bytes);
			output.flush();
		} catch (Exception e) {
			throw new JeesuiteBaseException(9999, "下载失败");
		}finally {			
			if(output != null){
				try {output.close(); } catch (Exception e) {}
			}
		}
	}
	
	@RequestMapping(value = "configs", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> queryConfigs(@RequestBody QueryConfigRequest query){
		
		boolean superAdmin = SecurityUtil.isSuperAdmin();
		if(StringUtils.isNotBlank(query.getEnv())){
			SecurityUtil.requireProfileGanted(query.getEnv());
		}
		
		Example example = new Example(AppconfigEntity.class);
		Criteria criteria = example.createCriteria();
		if(StringUtils.isNotBlank(query.getAppName())){
			criteria.andEqualTo("appName", query.getAppName());
		}
		if(StringUtils.isNotBlank(query.getEnv())){
			criteria.andEqualTo("env", query.getEnv());
		}else{
			if(!superAdmin){
				List<String> gantProfiles = SecurityUtil.getLoginUserInfo().getGantProfiles();
				if(gantProfiles.isEmpty()){
					return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(new ArrayList<>()),HttpStatus.OK);
				}
				criteria.andIn("env", gantProfiles);
			}
		}
		if(StringUtils.isNotBlank(query.getVersion())){
			criteria.andEqualTo("version", query.getVersion());
		}
		List<AppconfigEntity> list = appconfigMapper.selectByExample(example);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(list),HttpStatus.OK);
	}
	
	@RequestMapping(value = "config/options", method = RequestMethod.GET)
	public @ResponseBody List<KeyValuePair> getProfiles2(){
		List<KeyValuePair> result = new ArrayList<>();
		List<AppEntity> list = appMapper.selectAll();
		for (AppEntity entity : list) {
			result.add(new KeyValuePair(entity.getName(), entity.getAlias() + "("+entity.getName()+")"));
		}
		return result;
	}
	
	@RequestMapping(value = "config/delete/{id}", method = RequestMethod.GET)
	public ResponseEntity<WrapperResponseEntity> deleteConfig(@PathVariable("id") int id){
		AppconfigEntity entity = appconfigMapper.selectByPrimaryKey(id);
		if(entity != null)SecurityUtil.requireProfileGanted(entity.getEnv());
		int delete = entity == null ? 0 : appconfigMapper.deleteByPrimaryKey(id);
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(delete > 0),HttpStatus.OK);
	}
	
	@RequestMapping(value = "encrypt", method = RequestMethod.POST)
	public ResponseEntity<WrapperResponseEntity> encrypt功能Config(@RequestBody EncryptRequest param){
		SecurityUtil.requireProfileGanted(param.getEnv());
		AppEntity entity = appMapper.findByName(param.getAppName());
		String key = entity.getSecret() + param.getEnv();
		String encodeStr = CryptUtils.encode(key, param.getData());
		return new ResponseEntity<WrapperResponseEntity>(new WrapperResponseEntity(encodeStr),HttpStatus.OK);
	}
	
}
